from datetime import datetime, timedelta, timezone

from django.conf import settings
from django.db import models
from pymongo import MongoClient


class Location:
    '''
    Location in MongoDB
    { 
        "device_imei" : "866275036358993", 
        "start_timespan" : ISODate("2019-06-30T16:00:00.000+0000"), 
        "gps" : [
            {
                "altitude":"0.0",                   // 海拔
                "longitude" : 120.74657169265865, 
                "latitude" : 31.80207362760237, 
                "direction" : null,                 // 方向角, = bearing 
                "speed" : NumberInt(0), 
                "created_time" : ISODate("2019-06-30T16:00:10.406+0000"), 
                "occurred_time" : ISODate("2019-06-30T16:00:03.000+0000")
            }
        ], 
        "gps_count" : NumberInt(30), 
        "meta" : {
            "version" : 0.9, 
            "provider" : "kaiyi"
        }, 
        "vehicle_license_number" : "沪EG9631"
    }
    '''

    @classmethod
    def objects(cls):
        return cls()

    def __init__(self):
        TIMESPAN = 5
        CLIENT = MongoClient(settings.MONGO['URL'])
        DB = settings.MONGO['DB']
        CURSOR = CLIENT.get_database(DB)
        DATETIME_FORMAT = settings.REST_FRAMEWORK['DATETIME_FORMAT']
        self.cursor = CURSOR

    def _get_collection_name(self, dt: datetime):
        """获取最接近`dt`的collection
        """
        coll = dt.strftime('%Y%m')
        return coll

    def _get_collection_name_list(self, start_time: datetime, end_time: datetime):
        """将`start_time`和`end_time`之间的时间段转化为`collection_name`的list
        (2018-11-15, 2019-02-02)
        201811, 201812, 201901, 201902
        """
        coll_list = [self._get_collection_name(start_time)]
        st_year = start_time.year
        st_month = start_time.month
        while st_year != end_time.year or st_month != end_time.month:
            if st_month <= 11:
                st_month += 1
            else:
                st_year += 1
                st_month = 1
            coll_list.append(self._get_collection_name(datetime(
                year=st_year, month=st_month, day=1)))
        return coll_list

    def _get_time_range(start_time: datetime, end_time: datetime):
        """
        """
        one_day = timedelta(days=1)
        start_time_list = [start_time]
        end_time_list = []
        today = start_time
        while today <= end_time:
            tomorrow = today + one_day
            if tomorrow.month != today.month:
                start_time_list.append(tomorrow)
                end_time_list.append(today)

    def _get_position_list(self, coll_name, start_time: datetime, end_time: datetime,
                           device_imei=None, vehicle_license_number=None):
        """获取一辆车整个coll内某段时间的数据
        st = datetime(2019, 5, 8, 10)
        et = datetime(2019, 5, 8, 12)
        device_imei = '866275036358134'
        docus = Location.objects()._get_position_list('201905', st, et, device_imei)
        """
        p = {
            '_id': 0,
            'start_timespan': 1,
            'gps': {'longitude': 1, 'latitude': 1, 'occurred_time': 1}
        }
        f = {
            'start_timespan': {
                '$gte': start_time + timedelta(days=1),
                '$lt': end_time + timedelta(days=1),
            }
        }
        if device_imei:
            f['device_imei'] = device_imei
        if vehicle_license_number:
            f['vehicle_license_number'] = vehicle_license_number
        docus = self.cursor.get_collection(coll_name).aggregate(
            [{'$match': f}, {'$project': p}, {'$sort': {'start_timespan': 1}}]
        )
        return docus

    def get_position_list(self, start_time: datetime, end_time: datetime, *args, **kwargs):
        """
        """
        result = []
        coll_name_list = self._get_collection_name_list(start_time, end_time)
        for coll_name in coll_name_list:
            docus = self._get_position_list(coll_name, start_time, end_time, *args, **kwargs)
            result += (docus)
        return result


class VehicleStatus(models.Model):
    """车辆状态
    """
    StatusChoice = (
        ('ONLINE', '在线'),
        ('OFFLINE', '离线'),
        ('LONG_OFFLINE', '长时间离线'),
    )
    vehicle = models.ForeignKey('company.Vehicle', on_delete=models.CASCADE, db_index=True, verbose_name='关联车辆')
    status = models.CharField(max_length=15, choices=StatusChoice, verbose_name='状态')
    latitude = models.DecimalField(max_digits=18, decimal_places=15, null=True, blank=True, verbose_name='纬度')
    longitude = models.DecimalField(max_digits=18, decimal_places=15, null=True, blank=True, verbose_name='经度')
    altitude = models.DecimalField(max_digits=7, decimal_places=3, null=True, blank=True, verbose_name='海拔高度')
    speed = models.DecimalField(max_digits=11, decimal_places=2, default=0.0, verbose_name='车速km/h')
    last_time = models.DateTimeField(null=True, blank=True, verbose_name='最后时间')
    created_time = models.DateTimeField(auto_now_add=True, editable=False)
    modified_on = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'vehicle_status'
        verbose_name = '车辆状态'
        verbose_name_plural = verbose_name
